﻿using ParboiledSharp.parboiled.dataobjects;

namespace ParboiledSharp.parboiled.rules
{
    abstract class ContainerRule : Rule
    {
        private bool _forceRestoreState;
        private string name;

        public void SetName(string name)
        {
            this.name = name;
        }

        public string GetName()
        {
            return name;
        }

        protected void SetForceRestoreState(bool forceRestoreState)
        {
            _forceRestoreState = forceRestoreState;
        }

        protected override bool ExecuteRule(object rule, Context context)
        {
            int startMatchIndex = context.GetCurrentStreamIndex();
            context.InLevel();
            bool result = base.ExecuteRule(rule, context);
            context.OutLevel(!_forceRestoreState && result);

            if (_forceRestoreState)
            {
                context.SetCurrentStreamIndex(startMatchIndex - 1);
            }
            else
            {
                if (result)
                {
                    int endMatchIndex = context.GetCurrentStreamIndex();
                    context.SetMatch(startMatchIndex, endMatchIndex - startMatchIndex);
                }
                else
                {
                    context.SetCurrentStreamIndex(startMatchIndex);
                }
            }

            if (rule is Rule)
            {
                ((Rule)rule).EndRule(result, context);
            }

            _forceRestoreState = false;
            return result;
        }

        public override string ToString()
        {
            if (!string.IsNullOrEmpty(GetName()))
            {
                return GetName();
            }
            else
            {
                return base.ToString();
            }
        }
    }
}
